<template>
    <div class="wc-component my-table">
        <!-- 过滤条件、搜索条件 -->
        <div v-if="$scopedSlots.search" class="my-table__search">
            <slot name="search" :search="refresh" :loading="localLoading" />
        </div>
        <!-- 工具栏，例如，全选，需要拿到选中的数据，删除选中的行。 -->
        <!-- @todo 待定 $slots.footer -->
        <div v-if="$scopedSlots.toolbar" class="my-table__toolbar">
            <slot name="toolbar" :search="refresh" />
        </div>
        <!-- 表格 -->
        <div class="my-table__table">
            <el-table
                v-loading="localLoading"
                size="mini"
                :border="border"
                v-bind="$attrs"
                :data="localTableData"
                style="width: 100%"
                v-on="$listeners"
            >
                <!-- column 的 参数，详情见 文档 http://localhost:8085/#/zh-CN/component/table  中的  Table-column Attributes -->
                <template v-for="(th, key) in columns">
                    <el-table-column
                        v-if="isEmptColumn(th)"
                        :key="(Math.floor(Math.random() * 1000000)) + '_' + key"
                        v-bind="th"
                        :align="th.align || columnDefAlign"
                    />
                    <el-table-column
                        v-else
                        :key="(th.prop || Math.floor(Math.random() * 1000000)) + '_' + key"
                        :show-overflow-tooltip=" (th.hasOwnProperty('show-overflow-tooltip') || th.hasOwnProperty('showOverflowTooltip')) ?  th.hasOwnProperty('show-overflow-tooltip') || th.hasOwnProperty('showOverflowTooltip') : true "
                        v-bind="th"
                        :align="th.align || columnDefAlign"
                    >
                        <!--  自定义 table-column 内容 -->
                        <template slot-scope="scope">
                            <!-- {{ String(th.formatter)}} -->
                            <!-- 首先判断该 列 是不是 需要 通过 slot 内容分发 -->
                            <div v-if="th.isSlot || th.scopedSlots">
                                <slot
                                    :name="
                                        th.scopedSlots && th.scopedSlots.customRender
                                            ? th.scopedSlots.customRender
                                            : th.prop
                                    "
                                    :text="scope.row[th.prop]"
                                    :row="scope.row"
                                    :index="scope.$index"
                                    :scoped="scope"
                                />
                            </div>

                            <!-- 然后判断 是不是 默认的操作列 ， 也可以通过 slot 处理 -->
                            <!--  这里主要是操作列的 遍历， -->
                            <!-- operation -->
                            <!--  @click="clickFunHandler(oper.clickFun, scope,  $event)" -->
                            <div v-else-if="th.operation">
                                <el-button
                                    v-for="(oper, operkey) in th.operation"
                                    :key="(oper.prop || Math.floor(Math.random() * 1000000)) + '_' + operkey"
                                    v-bind="oper"
                                    size="small"
                                    :type="oper.type || 'text'"
                                    :is-refresh="oper.isRefresh"
                                    @click="oper.clickFun && oper.clickFun(scope.row, scope.$index, refresh, $event)"
                                >
                                    {{ oper.name }}
                                </el-button>
                            </div>

                            <!-- <div v-else-if="th.formatter">
                                <span v-if="!th.formatData">{{ scope.row[th.prop] }}</span>
                                <span v-else>
                                {{ th.formatData(scope.row[th.prop], scope.row, scope.$index) }}
                                </span>
                            </div> -->

                            <!-- 如果不是以上两种，则显示他的数据。但是， 在数据处理的过程当中，需要数据是不是需要格式化 -->
                            <div v-else>
                                <span v-if="!th.formatData" :key="th.prop + key">{{ scope.row[th.prop] }}</span>
                                <span v-else>
                                    {{ th.formatData(scope.row[th.prop], scope.row, scope.$index) }}
                                </span>
                            </div>
                        </template>
                        <template v-if="th.headerSlotName" slot="header">
                            <slot :name="th.headerSlotName" :column="th">{{ th.label }}</slot>
                        </template>
                    </el-table-column>
                </template>
                <slot />
                <template slot="empty">
                    <el-empty :image-size="200"></el-empty>
                </template>
            </el-table>
        </div>
        <!-- 分页 -->
        <div v-if="showLocalPage" class="my-table__pagination">
            <slot name="pagination">
                <el-pagination
                    :current-page.sync="localPageData.page"
                    :page-sizes="[5, 10, 20, 50, 100, 200, 300, 400]"
                    :page-size.sync="localPageData.pageSize"
                    :pager-count="pagerCount"
                    :layout="layout"
                    :total.sync="localPageData.total"
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange"
                />
            </slot>
        </div>
    </div>
</template>
<script>
/**
 * MyTable element 表格的二次封装，集成搜索，工具，表格，分页
 * @todo 工具栏的集成待处理。
 */
// import tableProps from "element/table"
// import tableProps from 'element-ui/lib/table';
//  ...tableProps.props,

export default {
    name: 'MyTableIndex',
    props: {
        data: {
            type: Array,
            default() {
                return []
            }
        },
        /**
         * 表格表头的数据，内部数据，参考 element el-table-column 的 参数。
         */
        columns: {
            type: Array,
            default() {
                return []
            }
        },
        // 请求数据的接口，如果存在，请务必是一个 promise
        listApi: {
            type: [Function, String],
            default: ''
        },
        // 是否进入就请求数据
        isRequestOnEntry: {
            type: Boolean,
            default: true
        },
        // 查询参数
        queryParams: {
            type: Object,
            default() {
                return {}
            }
        },
        dataField: {
            type: String,
            default: 'lists'
        },
        pageField: {
            type: String,
            default: 'page_no'
        },
        pageSizeField: {
            type: String,
            default: 'page_size'
        },
        totalField: {
            type: String,
            default() {
                return 'count'
            }
        },

        /**
         * 分页数据
         * page: page 当前页数，支持 .sync 修饰符
         * pageSize ： page-size 每页显示条目个数，支持 .sync 修饰符  后台返回的 page-size, 传给后台的是 limit
         * total： 总条目数
         * @example { page: 1, pageSize: 10, total: 400 }
         * @example {page_no: 1, page_size: 10, count: 200}
         */
        pageData: {
            type: Object,
            default() {
                return {}
            }
        },
        keyName: {
            type: String,
            default: 'abc'
        },
        tableList: {
            type: Array,
            default() {
                return []
            }
        },
        /**
         * pager-count	页码按钮的数量，
         * 当总页数超过该值时会折叠
         * number类型
         * 大于等于 5 且小于等于 21 的奇数	7
         */
        pagerCount: {
            type: Number,
            default: 7
        },
        layout: {
            type: String,
            default: 'prev, pager, next, jumper, sizes,  total'
        },
        pageSizes: {
            type: Array,
            defalut() {
                return [5, 10, 20, 50, 100, 200, 300, 400]
            }
        },
        // 是否前端分页。
        isLocalPagination: {
            type: Boolean,
            default: false
        },
        showPagination: {
            type: Boolean,
            default: true
        },
        loading: {
            type: Boolean,
            default: false
        },
        border: {
            type: Boolean,
            default: true
        }
    },

    data() {
        return {
            // 表格内的默认对齐方式， 如果 columns 里没有 align  字段，将默认取 columnDefAlign
            columnDefAlign: 'left',
            localPageData: {
                page: 1,
                pageSize: 10,
                total: 0
            },
            localTableData: [],
            localLoading: false
        }
    },
    computed: {
        listApiIsfunction() {
            if (this.listApi && typeof this.listApi === 'function') {
                return true
            }
            return false
        },
        tableList2() {
            return this.data
        },
        showLocalPage() {
            //
            return this.showPagination || this.$slots.pagination
        }
    },
    watch: {
        data(v) {
            if (!this.listApiIsfunction) {
                if (this.isLocalPagination && this.showPagination) {
                    const pageData = Object.assign({}, this.localPageData, {
                        [this.pageField]: 1,
                        [this.totalField]: this.data.length
                    })
                    this.setStatickPageData(pageData)
                    this.setStaticTableData()
                } else {
                    this.setLocalTableData()
                }
            }
        },
        loading(v) {
            if (!this.listApiIsfunction) {
                this.setLoading(v)
            }
        },
        pageData: {
            deep: true,
            handler() {
                if (!this.listApiIsfunction) {
                    this.initLocalPageData()
                }
            }
        }
    },
    created() {
        this.localPageData = {
            [this.pageField]: 1,
            [this.pageSizeField]: 10,
            [this.totalField]: 0
        }
    },
    mounted() {
        this.setStatickPageData()
        this.setLocalTableData()
        this.initLocalPageData()
        if (this.isRequestOnEntry) {
            this.getTableData()
        }
        this.setLoading(this.loading)
    },
    methods: {
        /**
         * 需要判断 column 参数
         * el-table-column 部分功能，不允许 标签内有任何内容，所以，检测 column  是否符合这种情况，如果是，则直接 写 <el-table-column v-bind="th" :key="" />
         * 另个一种情况则是，检测缺失的 字段，如果都满足，就直接 渲染。
         */
        isEmptColumn(column) {
            const columnKey = Object.keys(column)
            const columnNotkeys = ['formatter', 'type']
            const bool = columnNotkeys.some(item => columnKey.includes(item))
            return bool
        },

        setLocalTableData(data) {
            const tableData = data || this.data
            if (Array.isArray(tableData)) {
                this.localTableData = JSON.parse(JSON.stringify(tableData))
            }
        },

        initLocalPageData() {
            this.localPageData = Object.assign({}, this.localPageData, this.pageData)
            // this.$emit('update:page-data', this.localPageData)
        },

        setLocalPageData(pageData) {
            this.localPageData = pageData
            // 返回一个分页信息出去，相当于支持开发人员，自定义分页功能。
            this.$emit('update:page-data', pageData)

            // 返回一个分页事件出去，相当于支持开发人员，自定义分页功能。
            this.$emit('pagination', pageData)
        },
        // 获取 listApi 请求的参数，除了过滤条件中的参数之外，还应该集成分页的数据
        getListApiParams(params = {}) {
            const pagination = {
                [this.pageField]: this.localPageData[this.pageField],
                [this.pageSizeField]: this.localPageData[this.pageSizeField]
            }
            console.log('abcd', pagination, this.localPageData)
            return Object.assign({}, this.queryParams, params, {
                ...pagination
            })
        },
        refresh(config = {}) {
            const pageData = Object.assign({}, this.localPageData, {
                [this.pageField]: 1
            })
            this.setLocalPageData(pageData)
            this.getTableData(config)
            this.$emit('refresh')
        },

        /**
         * 获取表格数据
         * 需要请示接口，请求参数，返回
         */
        getTableData(config = {}) {
            const vm = this
            // 如果 传进来的 data 有数据，则不处理。
            // if (this.data.length) {
            //     // this.$emit("update:data", this.data)
            //     return
            // }
            // 获取参数，这个参数从哪里来，应该是有一个 queryParams 的参数，这个参数，可以是传进来的，也可以是 内部获取的。
            
            this.$nextTick(() => {
                const params = vm.getListApiParams(config)
                console.log('myTableData params', params)
                if (this.listApiIsfunction) {
                    try {
                        this.setLoading(true)
                        this.listApi(params)
                            .then(res => {
                                vm.$emit('update:data', res[vm.dataField])
                                vm.setLocalTableData(res[vm.dataField])
                                // 这里需要返回分页的信息出去，同时，需要设置分页信息。因为随着过滤条件的不同，分页信息中的总条数可能会不一样。
                                const localPageData = Object.assign({}, vm.localPageData, {
                                    pageSize: res[vm.pageSizeField] || 10,
                                    total: res[vm.totalField]
                                })
                                vm.setLocalPageData(localPageData)
                                // 把请求到的数据，直接返回，以供开发人员自定义
                                vm.$emit('load-data', res)
                                vm.setLoading(false)
                            })
                            .catch(err => {
                                vm.setLoading(false)
                                console.error('MyTable catch', err.message || err.msg)
                            })
                    } catch (error) {
                        vm.setLocalTableData([])
                        vm.setLoading(false)
                        // listApi 很有可能不是一个 promise  方法
                    }
                } else if (this.isLocalPagination) {
                    // 表示前端静态分页。
                    //
                    // 根据分页信息对数据分割
                    this.setStaticTableData()
                }
            })
           
        },

        setStaticTableData() {
            if (this.listApiIsfunction && typeof this.listApiIsfunction === 'function') {
                return
            }
            if (!this.showPagination) {
                this.setLocalTableData()
                return
            }
            const dataCopy = JSON.parse(JSON.stringify(this.data))
            const pagetionTableData = dataCopy.splice(
                (this.localPageData.page - 1) * this.localPageData.pageSize,
                this.localPageData.pageSize
            )
            this.setLocalTableData(pagetionTableData)
        },

        setStatickPageData() {
            if (!this.listApiIsfunction) {
                const localPageData = Object.assign({}, this.localPageData, {
                    total: this.data.length
                })
                this.setStaticLocalPageData(localPageData)
            }
        },
        setStaticLocalPageData(pageData) {
            this.localPageData = pageData
            this.$emit('pagination', pageData)
        },

        /**
         * 每页条数发生变化后，当前页应该重置为第一页。然后重新发起请求。
         * 如果后台分页，还需要重新发起请求。
         **/
        handleSizeChange(val) {
            const pageData = Object.assign({}, this.localPageData, {
                [this.pageField]: 1
            })
            delete pageData.redisSign
            delete this.queryParams.redisSign
            this.setLocalPageData(pageData)
            this.getTableData()
        },

        /**
         * 当前页面发生变化时，索引值从 1 开始。
         * 后台分页重新请求数据。
         * 前台分页，重新对 this.data 做处理。
         */
        handleCurrentChange(val) {
            const pageData = Object.assign({}, this.localPageData, {
                [this.pageField]: val
            })
            delete pageData.redisSign
            delete this.queryParams.redisSign
            this.setLocalPageData(pageData)
            this.getTableData()
        },
        // 当某一行被点击时会触发该事件
        rowClick(row, column, event) {
            this.$emit('row-click', row, column, event)
        },
        setLoading(status) {
            this.localLoading = status
            if (this.listApiIsfunction) {
                this.$emit('loading', this.localLoading)
                this.$emit('update:loading', this.localLoading)
            }
        },
        clickFunHandler(callback, scope, event) {
            callback(s)
        }
    }
}
</script>

<style scoped>
.my-table__search {
    margin-bottom: 5px;
}
.my-table__pagination {
    margin-top: 10px;
    text-align: right;
}
</style>
